package com.yycx.common.security.passwordencoder;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Md5PasswordEncoder implements CustomPasswordEncoder {
    //md5加密
    private static String algorithm = "MD5";
    //密码强度
    private static int hashIterations = 2;
    //
    private final static String[] HEX_DIGITS = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
    //登录账号
    private String account;
    //盐值
    private String salt;

    private static Md5PasswordEncoder instance = new Md5PasswordEncoder();

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public Md5PasswordEncoder() {
    }

    //以单例模式构造
    public static Md5PasswordEncoder getInstance() {
        return instance;
    }

    private String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (byte value : b) {
            resultSb.append(byteToHexString(value));
        }
        return resultSb.toString();
    }

    private String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return HEX_DIGITS[d1] + HEX_DIGITS[d2];
    }

    /**
     * MD5加密
     *
     * @param rawPassword 原始密码
     * @return 加密后的md5密文
     */
    @Override
    public String encode(CharSequence rawPassword) {
        String result = null;
        try {
            String password = rawPassword.toString();
            String mySalt = account + salt;
            byte[] hash = instance.hash(password.getBytes(), mySalt.getBytes(), hashIterations);
            result = byteArrayToHexString(hash);
        } catch (Exception ignored) {
        }
        return result;
    }

    /**
     * MD5加密
     *
     * @param rawPassword 原始密码
     * @param account     用户账号
     * @param salt        盐
     * @return 加密后的md5密文
     */
    @Override
    public String encode(CharSequence rawPassword, String account, String salt) {
        this.account = account;
        this.salt = salt;
        return encode(rawPassword);
    }

    /**
     * 密码比较
     *
     * @param rawPassword     原始密码
     * @param encodedPassword 加密后的密码
     * @return boolean
     */
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return encodedPassword.equals(encode(rawPassword));
    }

    private MessageDigest getDigest(String algorithmName) {
        try {
            return MessageDigest.getInstance(algorithmName);
        } catch (NoSuchAlgorithmException var4) {
            String msg = "No native '" + algorithmName + "' MessageDigest instance available on the current JVM.";
        }
        return null;
    }

    private byte[] hash(byte[] bytes, byte[] salt, int hashIterations) {
        MessageDigest digest = this.getDigest(algorithm);
        if (salt != null) {
            digest.reset();
            digest.update(salt);
        }

        byte[] hashed = digest.digest(bytes);
        int iterations = hashIterations - 1;

        for (int i = 0; i < iterations; ++i) {
            digest.reset();
            hashed = digest.digest(hashed);
        }
        return hashed;
    }

    public static void main(String[] args) {
        Md5PasswordEncoder instance = Md5PasswordEncoder.getInstance();
        instance.setSalt("0f02e630114ab0ae26f48aa3e4a2ec0e");
        instance.setAccount("superadmin");
        String encode = instance.encode("123456","superadmin","0f02e630114ab0ae26f48aa3e4a2ec0e");
        System.out.println("encode:" + encode);
        boolean matches = instance.matches("123456", encode);
        System.out.println(matches);
    }


}

